package cn.jimmie.lib.qlog;

import android.content.Context;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import cn.jimmie.lib.qlog.interceptor.AndroidLogInterceptor;
import cn.jimmie.lib.qlog.interceptor.CommonHeaderInterceptor;
import cn.jimmie.lib.qlog.interceptor.HeaderInterceptor;
import cn.jimmie.lib.qlog.interceptor.Interceptor;
import cn.jimmie.lib.qlog.support.AlException;
import cn.jimmie.lib.qlog.support.AlString;

/**
 * Func :
 *
 * <p> Create Time:  2019-12-18 10:54 </p>
 * <p> @author Jimmie.Qian  </p>
 */
final class QLogProxy implements Proxy, RecyclerLogExecutor.OnMessageListener {
    private static final long DEFAULT_LOG_SIZE = 8 * 1024 * 1024;

    private List<Interceptor> interceptors = new ArrayList<>();
    private HeaderInterceptor headerInterceptor = new CommonHeaderInterceptor();
    private RecyclerLogExecutor executor;
    private boolean isInit = false;

    QLogProxy() {
        executor = new RecyclerLogExecutor(this);
    }

    @Override
    public void init(QLog.Config conf) {
        if (conf.appCtx == null) return;
        isInit = true;
        Context ctx = conf.appCtx.getApplicationContext();

        if (conf.logMaxSize <= 0) conf.logMaxSize = DEFAULT_LOG_SIZE;

        if (conf.level == null) conf.level = QLogLevel.INFO;

        if (AlString.empty(conf.tag)) conf.tag = "QLogger";

        if (AlString.empty(conf.logPath))
            conf.logPath = ctx.getExternalFilesDir("") + File.separator + "QLogger.txt";

        if (conf.interceptors == null || conf.interceptors.isEmpty()) {
            conf.consoleInterceptor(new AndroidLogInterceptor(), true);
        }
        interceptors.addAll(conf.interceptors);

        if (conf.headerInterceptor == null) {
            conf.headerInterceptor = new CommonHeaderInterceptor();
        }
        this.headerInterceptor = conf.headerInterceptor;

        headerInterceptor.init(Options.build(conf));
        new Thread(executor, "qLogger-thread").start();
    }


    @Override
    public void release() {
        for (Interceptor interceptor : interceptors)
            interceptor.release();
        executor.release();
        interceptors.clear();
    }

    @Override
    public void v(QFormat format, String source, Object... args) {
        handleLevelLog(QLogLevel.VERBOSE, format, source, args);
    }

    @Override
    public void d(QFormat format, String source, Object... args) {
        handleLevelLog(QLogLevel.DEBUG, format, source, args);
    }

    @Override
    public void i(QFormat format, String source, Object... args) {
        handleLevelLog(QLogLevel.INFO, format, source, args);
    }

    @Override
    public void w(QFormat format, String source, Object... args) {
        handleLevelLog(QLogLevel.WARN, format, source, args);
    }

    @Override
    public void e(QFormat format, String source, Object... args) {
        handleLevelLog(QLogLevel.ERROR, format, source, args);
    }

    @Override
    public void e(Throwable t) {
        String trace = AlException.fullTrace(t);
        handleLevelLog(QLogLevel.ERROR, QFormat.DEFAULT, trace);
    }

    private void handleLevelLog(QLogLevel level, QFormat format, String source, Object... args) {
        if (!isInit) return;
        String message = format.format(source);
        message = AlString.format(message, args);
        if (AlString.empty(message)) return;
        message = headerInterceptor.prefixInfo() + message;
        executor.add(level, message);
    }

    @Override
    public void onPreQueueStart() {
        for (Interceptor interceptor : interceptors)
            interceptor.init(headerInterceptor);
    }

    @Override
    public void onLogReach(QLogLevel level, String message) {
        if (level == null || AlString.empty(message)) return;

        for (Interceptor interceptor : interceptors) {
            if (interceptor.enabled()) interceptor.submit(level, message);
        }
    }
}
